#include "keyboard_wrapper.h"
#include "wlroots-full.hpp"
#include "server.h"

KeyboardWrapper::KeyboardWrapper(struct wlr_input_device *device, Server* server)
    : m_server(server)
{
    m_wlr_keyboard = wlr_keyboard_from_input_device(device);
    /* We need to prepare an XKB keymap and assign it to the keyboard. This
     * assumes the defaults (e.g. layout = "us"). */
    struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, NULL,
                                                          XKB_KEYMAP_COMPILE_NO_FLAGS);

    wlr_keyboard_set_keymap(m_wlr_keyboard, keymap);
    xkb_keymap_unref(keymap);
    xkb_context_unref(context);
    wlr_keyboard_set_repeat_info(m_wlr_keyboard, 25, 600);

    m_modifiers.connect(&m_wlr_keyboard->events.modifiers, [=](void* data) {
        handle_modifiers();
    });

    m_key.connect(&m_wlr_keyboard->events.key, [=](void *data) {
        struct wlr_keyboard_key_event *event = (struct wlr_keyboard_key_event*)data;
        handle_key(event);
    });

    m_destroy.connect(&device->events.destroy, [=](void* data) {
        handle_destroy();
    });
}

KeyboardWrapper::~KeyboardWrapper()
{
}

void KeyboardWrapper::handle_modifiers()
{
#if 0
    wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard);
    /* Send modifiers to the client. */
    wlr_seat_keyboard_notify_modifiers(keyboard->server->seat,
                                       &m_wlr_keyboard->modifiers);
#else
    sig_modifiers.emit(m_wlr_keyboard);
#endif
}

void KeyboardWrapper::handle_key(wlr_keyboard_key_event *event)
{
#if 0
    // struct wlr_seat *seat = server->seat;

    /* Translate libinput keycode -> xkbcommon */
    uint32_t keycode = event->keycode + 8;
    /* Get a list of keysyms based on the keymap for this keyboard */
    const xkb_keysym_t *syms;
    int nsyms = xkb_state_key_get_syms(m_wlr_keyboard->xkb_state, keycode, &syms);

    bool handled = false;
    uint32_t modifiers = wlr_keyboard_get_modifiers(m_wlr_keyboard);
    if ((modifiers & WLR_MODIFIER_ALT) &&
        event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
        /* If alt is held down and this button was _pressed_, we attempt to
         * process it as a compositor keybinding. */
        for (int i = 0; i < nsyms; i++) {
            handled = handle_keybinding(server, syms[i]);
        }
    }

    if (!handled) {
        /* Otherwise, we pass it along to the client. */
        wlr_seat_set_keyboard(seat, m_wlr_keyboard);
        wlr_seat_keyboard_notify_key(seat, event->time_msec,
                                     event->keycode, event->state);
    }
#else
    sig_key.emit(m_wlr_keyboard, event);
#endif
}

void KeyboardWrapper::handle_destroy()
{
    m_modifiers.disconnect();
    m_key.disconnect();
    sig_destroy.emit();
    m_destroy.disconnect();
    delete this;
}
